package db

import (
	"bp/db/sqlc/ctype"
	"database/sql"
	"encoding/json"
	"time"

	// "github.com/golang/protobuf/ptypes"
	"github.com/golang/protobuf/ptypes/timestamp"
	"google.golang.org/protobuf/types/known/timestamppb"
)

// NSFromString string -> sql.NullString
func NSFromString(s string) sql.NullString {
	if s == "" {
		return sql.NullString{}
	}
	return sql.NullString{
		String: string(s),
		Valid:  true,
	}
}

// NInt64ToInt64 sql.NullInt64 -> int64
func NInt64ToInt64(ni sql.NullInt64) int64 {
	if ni.Valid {
		return ni.Int64
	}
	return 0
}

// NInt32ToInt32 sql.NullInt64 -> int32
func NInt32ToInt32(ni sql.NullInt32) int32 {
	if ni.Valid {
		return ni.Int32
	}
	return 0
}

// NInt64FromInt64 int64 -> sql.NullInt64
func NInt64FromInt64(i int64) sql.NullInt64 {
	if i == 0 {
		return sql.NullInt64{}
	}
	return sql.NullInt64{
		Int64: i,
		Valid: true,
	}
}

// NInt32FromInt32 int32 -> sql.NullInt32
func NInt32FromInt32(i int32) sql.NullInt32 {
	if i == 0 {
		return sql.NullInt32{}
	}
	return sql.NullInt32{
		Int32: i,
		Valid: true,
	}
}

// NRawMessageToRawMessage ctype.NullRawMessage -> json.RawMessage
func NRawMessageToRawMessage(nrm ctype.NullRawMessage) json.RawMessage {
	if nrm.Valid {
		val, _ := nrm.Value()
		return val.([]byte)
	}
	return json.RawMessage{}
}

// NRawMessageFromRawMessage json.RawMessage -> ctype.NullRawMessage
func NRawMessageFromRawMessage(rm json.RawMessage) ctype.NullRawMessage {
	if len(rm) > 0 {
		return ctype.NullRawMessage{
			Valid:      true,
			RawMessage: rm,
		}
	}
	return ctype.NullRawMessage{
		Valid:      false,
		RawMessage: json.RawMessage{},
	}
}

// GoNTimeToPBTimestamp sql.NullTime -> *timestamp.Timestamp
func GoNTimeToPBTimestamp(nt sql.NullTime) *timestamp.Timestamp {
	if nt.Valid {
		return GoTimeToPBTimestamp(nt.Time)
	}
	return &timestamp.Timestamp{}
}

// GoTimeToPBTimestamp time.Time -> *timestamp.Timestamp
func GoTimeToPBTimestamp(t time.Time) *timestamp.Timestamp {
	pbtz := timestamppb.New(t)
	// pbtz, err := ptypes.TimestampProto(t)
	// if err != nil {
	// 	return &timestamp.Timestamp{}
	// }
	return pbtz
}

// PBTimestampToGoTime *timestamp.Timestamp -> time.Time
func PBTimestampToGoTime(ts *timestamp.Timestamp) (t time.Time) {
	err := ts.CheckValid()
	if err != nil {
		return time.Time{}
	}
	t = ts.AsTime()
	// t, err := ptypes.Timestamp(ts)
	// if err != nil {
	// 	return time.Time{}
	// }
	return
}

// PBTimestampToGoTime *timestamp.Timestamp -> sql.NullTime
func PBTimestampToGoNTime(ts *timestamp.Timestamp) sql.NullTime {
	return NTimeFromTime(PBTimestampToGoTime(ts))
}

// NTimeFromTime time.Time -> sql.NullTime
func NTimeFromTime(t time.Time) sql.NullTime {
	return sql.NullTime{
		Time:  t,
		Valid: true,
	}
}
